package c2.cross.business.championrace;

import cate.game.pvp.championrace.data.ChampionRaceRecord;
import cate.game.pvp.championrace.data.ChampionRaceSpec;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.annotation.Transient;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

public class ChampionRaceRecordData {
    private Map<String, Map<String, ChampionRaceRecord>> records;

    @Transient
    private final Object recordLock = new Object();

    public void initialize() {
        if (records == null) {
            records = new HashMap<>();
        }
    }

    public List<ChampionRaceRecord> getRecords(ChampionRaceSpec spec) {
        if (Objects.isNull(spec)) {
            return Collections.emptyList();
        }
        ChampionRaceSpec param = ChampionRaceSpec.ofNullStep(spec);
        List<ChampionRaceRecord> rs;
        synchronized (recordLock) {
            Map<String, ChampionRaceRecord> maps = records.get(param.toString());
            rs = CollectionUtils.isEmpty(maps) ? Lists.newArrayList() : Lists.newArrayList(maps.values());
        }
        return rs;
    }

    public List<ChampionRaceRecord> getRecords(ChampionRaceSpec from, ChampionRaceSpec to) {
        if (Objects.isNull(to)) {
            return Collections.emptyList();
        }
        List<ChampionRaceRecord> rs;
        synchronized (recordLock) {
            rs = records.values().stream().flatMap(e -> e.values().stream()).filter(rd -> {
                ChampionRaceSpec spec = rd.getSpec();
                if (from == null) {
                    return spec.getPeriod() == to.getPeriod() && spec.getRound() == to.getRound();
                }
                return Objects.compare(spec, from, ChampionRaceSpec::compareTo) >= 0
                        && Objects.compare(to, spec, ChampionRaceSpec::compareTo) >= 0;
            }).collect(Collectors.toList());
        }
        return rs;
    }

    public List<ChampionRaceRecord> getRecords(String uid, ChampionRaceSpec from, ChampionRaceSpec to) {
        if (Objects.isNull(to)) {
            return Collections.emptyList();
        }
        List<ChampionRaceRecord> recordsList;
        synchronized (recordLock) {
            recordsList = records.values().stream().flatMap(e -> e.values().stream())
                    .filter(rd -> {
                        if (rd.getSpec().getPeriod() == 1) {
                            return StringUtils.equalsIgnoreCase(rd.getIdA(), uid);
                        } else {
                            return StringUtils.equalsIgnoreCase(rd.getIdA(), uid)
                                    || StringUtils.equalsIgnoreCase(rd.getIdB(), uid);
                        }
                    })
                    .filter(rd -> {
                        if (Objects.isNull(from)) {
                            ChampionRaceSpec spec = rd.getSpec();
                            return spec.getPeriod() == to.getPeriod() && spec.getRound() == to.getRound();
                        } else {
                            ChampionRaceSpec spec = rd.getSpec();
                            return Objects.compare(spec, from, ChampionRaceSpec::compareTo) >= 0
                                    && Objects.compare(to, spec, ChampionRaceSpec::compareTo) >= 0;
                        }
                    })
                    .collect(Collectors.toList());
        }
        return recordsList;
    }

    public void addRecord(ChampionRaceRecord record) {
        synchronized (recordLock) {
            String specStr = record.getSpec().toString();
            if (!records.containsKey(specStr) || !records.get(specStr).containsKey(record.getRid())) {
                records.putIfAbsent(specStr, new HashMap<>());
                records.get(specStr).put(record.getRid(), record);
            }
        }
    }

    public void clear() {
        synchronized (recordLock) {
            records.clear();
        }
    }
}
